<?php

namespace collections\map;

class TreeEntry implements Entry
{
    const RED = false;
    const BLACK = true;

    /** @var mixed */
    public $key;
    /** @var mixed */
    public $value;
    /** @var boolean */
    public $color;

    /** @var TreeEntry */
    public $left;
    /** @var TreeEntry */
    public $right;
    /** @var TreeEntry */
    public $parent;

    public function __construct($key, $value, $parent) {
        $this->key = $key;
        $this->value = $value;
        $this->parent = $parent;
    }

    public function getKey() {return $this->key;}
    public function getValue() {return $this->value;}
    public function setValue($value) {
        $oldValue = $this->value;
        $this->value = $value;
        return $oldValue;
    }

    public function valEquals($o1, $o2) {
        return is_null($o1) ? is_null($o2) : $o1 == $o2;
    }

    public function equals($o) {
        if (!($o instanceof Entry)) {
            return false;
        }
        return $this->key == $o->getKey() && $this->value == $o->getValue();
    }

    public function __toString() {
        return $this->key . "=" . $this->value;
    }

    /**
     * @param $t TreeEntry
     * @return null
     */
    public static function successor($t) {
        if (is_null($t)) {
            return null;
        } elseif ($t->right != null) {
            $p = $t->right;
            while ($p->left != null) {$p = $p->left;}
            return $p;
        } else {
            $p = $t->parent;
            $ch = $t;
            while (!is_null($p) && $ch === $p->right) {
                $ch = $p;
                $p = $p->parent;
            }
            return $p;
        }
    }

    /**
     * @param $t TreeEntry
     * @return null
     */
    public static function predecessor($t) {
        if (is_null($t)) {
            return null;
        } elseif ($t->left != null) {
            $p = $t->left;
            while ($p->right != null) {$p = $p->right;}
            return $p;
        } else {
            $p = $t->parent;
            $ch = $t;
            while (!is_null($p) && $ch === $p->left) {
                $ch = $p;
                $p = $p->parent;
            }
            return $p;
        }
    }

    /**
     * @param TreeEntry $p
     * @return bool
     */
    public static function colorOf($p) {return is_null($p) ? self::BLACK : $p->color;}

    /**
     * @param TreeEntry $p
     * @return TreeEntry|null
     */
    public static function parentOf($p) {return is_null($p) ? null : $p->parent;}

    /**
     * @param $p TreeEntry
     * @param $c
     */
    public static function setColor($p, /* boolean */$c) {
        if (!is_null($p)) {$p->color = $c;}
    }

    /**
     * @param TreeEntry $p
     * @return TreeEntry|null
     */
    public static function leftOf($p) {return is_null($p) ? null : $p->left;}

    /**
     * @param $p TreeEntry
     * @return TreeEntry|null
     */
    public static function rightOf($p) {return is_null($p) ? null : $p->right;}
}